<script lang="ts" setup>
import { onBeforeMount, reactive, ref } from 'vue'
import { useUserStore } from '@/stores/user'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { onBeforeRouteLeave, useRouter } from 'vue-router'

const props = defineProps<{
    // 从父组件传递过来的可选参数 type
    type?: string
}>()
// 向父组件传递任务完成事件
const emit = defineEmits(['success'])

const userStore = useUserStore()
const disabledButton = ref(false)
// 表单实例
const formRef = ref<FormInstance>()

// 组件被挂载之前调用(已完成响应式状态的设置，但未渲染DOM)
onBeforeMount(() => {
    // 开发环境下打印数据
    if (import.meta.env.DEV) console.log('Form onBeforeMount')
    // 如果已登录，跳转到首页
    if (userStore.isLogged) {
        const router = useRouter()
        // 跳转到首页
        router.push('/')
    }
})

// 路由更新前调用
onBeforeRouteLeave((to, from) => {
    // 开发环境下打印数据
    if (import.meta.env.DEV)
        console.log(`Form onBeforeRouteLeave {to: ${to.path}, from: ${from.path}}`)
    // 如果是从注册页面前往其他页面，且未在已登录状态，重置邮箱
    if (props.type === 'signup' && !userStore.isLogged) {
        // 重置邮箱
        userStore.user.email = ''
    }
    // 如果目的组件不是login或者signup，重置密码
    if (to.name !== 'login' && to.name !== 'signup') {
        // 重置密码
        userStore.user.password = ''
        userStore.user.confirmPassword = ''
    }
})

// 表单验证
const formRules = reactive<FormRules>({
    name: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
    email: [
        // 邮箱注册时必填，登陆时不需要
        { required: props.type === 'signup', message: '请输入邮箱', trigger: 'blur' },
        { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
    ],
    password: [
        { required: true, message: '请输入密码', trigger: 'blur' },
        { min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: ['blur', 'change'] },
        {
            validator: (rule, value, callback) => {
                // 有时用户输入到确认密码后，发现之前的密码有误，修改了之前的密码
                // 如果不增加这个校验逻辑，用户还需要重新操作确认密码输入框才能触发校验
                if (props.type === 'signup' && userStore.user.confirmPassword !== '') {
                    // 触发确认密码的验证
                    formRef.value?.validateField('confirmPassword').catch((err) => {
                        if (import.meta.env.DEV) console.log(err)
                    })
                }
                callback()
            },
            trigger: ['blur', 'change']
        }
    ],
    confirmPassword: [
        // 确认密码注册时必填，登陆时不需要
        { required: props.type === 'signup', message: '请再次输入密码', trigger: 'blur' },
        { min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: ['blur', 'change'] },
        {
            validator: (rule, value, callback) => {
                if (value === userStore.user.password) {
                    callback()
                } else {
                    callback(new Error('两次输入密码不一致'))
                }
            },
            trigger: ['blur', 'change']
        }
    ]
})

function post(path: string = 'login') {
    if (!formRef.value) return
    // 防止重复提交
    disabledButton.value = true
    // 开发环境下打印数据
    if (import.meta.env.DEV) console.log(`Form ${path}`)
    formRef.value?.validate((valid) => {
        if (!valid) {
            // 校验不通过，不执行注册
            if (import.meta.env.DEV) console.log(`Form ${path} validate failed`)
            ElMessage.error('请检查输入格式是否正确')
            // 重置按钮状态
            disabledButton.value = false
            return false
        }
        if (import.meta.env.DEV) console.log(`Form ${path} validate success`)
        // 校验通过，注册
        userStore
            .postUser(path)
            .then((data) => {
                if (!data) {
                    ElMessage.error('服务器未响应数据')
                    return
                }
                if (data.errMsg) {
                    ElMessage.error(data.errMsg)
                    return
                }
                emit('success')
            })
            .catch((err) => {
                if (err) {
                    ElMessage.error(err.message)
                }
            })
            .finally(() => {
                // 重置按钮状态
                disabledButton.value = false
            })
    })
}

// submit按钮的点击事件
const submit = () => {
    post(props.type)
}
</script>

<template>
    <div class="form-box">
        <el-form
            ref="formRef"
            v-loading="disabledButton"
            :model="userStore.user"
            :rules="formRules"
            class="form"
            hide-required-asterisk
            label-position="top"
            label-width="80px"
            scroll-to-error
            status-icon
            style="max-width: 300px"
            @keydown.enter="submit">
            <el-form-item autocomplete="username" label="用户名" prop="name">
                <el-input v-model="userStore.user.name" />
            </el-form-item>
            <el-form-item v-if="type === 'signup'" autocomplete="email" label="邮箱" prop="email">
                <el-input v-model="userStore.user.email" />
            </el-form-item>
            <el-form-item label="密码" prop="password">
                <el-input
                    v-model="userStore.user.password"
                    :autocomplete="type === 'signup' ? 'new-password' : 'off'"
                    show-password />
            </el-form-item>
            <el-form-item v-if="type === 'signup'" label="确认密码" prop="confirmPassword">
                <el-input
                    v-model="userStore.user.confirmPassword"
                    :disabled="!userStore.user.password"
                    autocomplete="new-password"
                    show-password />
            </el-form-item>
            <el-form-item>
                <el-button :disabled="disabledButton" class="submit" type="primary" @click="submit">
                    {{ type === 'signup' ? '注册' : '登录' }}
                </el-button>
            </el-form-item>
        </el-form>
    </div>
</template>
<!-- 私有样式,只会影响当前组件的元素 -->
<style scoped>
.form-box {
    width: 100%;
    height: 100%;
    text-align: center;
}

.form {
    margin: 0 auto;
}

.submit {
    width: 100%;
}
</style>